﻿using System;
using System.Collections.Generic;
using TI;
using System.IO;
using TI_EntityLib;
using System.Net;
using System.Text.RegularExpressions;
using TI_EntityLib.TiEntityObjects.DayLog;
using TiEntityObject.Transport;


namespace TI_FTP
{
   
   public enum FtpExceptionType { FtpFolderNotFound };

   public class FtpException : TiException {
        public FtpExceptionType ErrType { get; set; }
    }
   
   public class FtpLoader
   {
       private DateTime targetDay = DateTime.Now;
       public DateTime TargetDay { get { return targetDay; } set { targetDay = value; } }

       private TransportConfig config = null;
       public FtpLoader(TransportConfig config)
       {
          this.config = config;
       }

       public void RUN(DateTime day)
       {
           
           this.TargetDay = day;

           Helper.FileTools.СeckAndCreateFolder(config.FtpRoot);
         
           List<string> folders = GetFileList(config.URL);
           

           foreach (string i in folders)
           {   
               if(isFolder (i))
                    ProcessFolder(i);
           }

           
       }

       /// <summary>
       /// Обработка текщей папки
       /// </summary>
       /// <param name="folderName"></param>
       private void ProcessFolder(string folderName)
       {
           // Notification
           ProcessDayFolder(folderName + @"/notifications/daily/", folderName); 
           // Contract
           ProcessDayFolder(folderName + @"/contracts/daily/", folderName); 
           // Protocol
           ProcessDayFolder(folderName + @"/protocols/daily/", folderName); 
       }

       private void ProcessDayFolder(string ftpFolderName,string diskFolderName)
       {
           List<string> l = GetFileList(config.GetFolderUrl(ftpFolderName));
           Console.WriteLine("Файлов в папке " + ftpFolderName + " :" + l.Count.ToString());
           List<string> files = SelectFileListOfDay(ftpFolderName, l);
           Console.WriteLine("Изменено:" + files.Count.ToString());
           DownloadFolderFileList(ftpFolderName, diskFolderName, files);

       }

       private void DownloadFolderFileList(string ftpFolderName, string diskFolderName, List<string> source)
       {
           string diskUrl = string.Empty;
           string ftpUrl = string.Empty;

           foreach (string i in source)
           {
               diskUrl = config.GetStoreFilePath(targetDay, diskFolderName, i);
               ftpUrl = config.GetFileURL(ftpFolderName, i);
               DownloadFile(ftpUrl, diskUrl);
               Console.WriteLine(diskUrl+":OK");
           }
       }

       private bool fileExists(string fileName )
       {
           return File.Exists(fileName); 
           //FileInfo fi= new FileInfo(fileName);
           //string[] r = Directory.GetFiles(fi.DirectoryName);
           //fileName = fileName.Replace(fi.DirectoryName, string.Empty);
           //int dot=fileName .IndexOf (".");
           //fileName = fileName.Substring(1, dot - 1);
           //foreach (string s in r)
           //{
           //    if (s.IndexOf(fileName) > -1)
           //        return true;
           //}
           //return false;
       }

       private void DownloadFile(string fileUrl,string targetFileName) {

           if (fileExists(targetFileName))
                          return;

           FtpWebRequest request = (FtpWebRequest)WebRequest.Create(fileUrl);
           request.Method = WebRequestMethods.Ftp.DownloadFile;
           FtpWebResponse response = (FtpWebResponse)request.GetResponse();
           Stream responseStream = response.GetResponseStream();
           using (Stream file = File.OpenWrite(targetFileName))
           {
               CopyStream(responseStream, file);
           }
       }

       private static void CopyStream(Stream input, Stream output)
       {
           byte[] buffer = new byte[10 * 1024];
           int len;
           while ((len = input.Read(buffer, 0, buffer.Length)) > 0)
           {
               output.Write(buffer, 0, len);
           }
       }

            
       private List<string> SelectFileListOfDay(string folderName, List<string> fullFileList)
       {
           List<string> result = new List<string>();
           DateTime d = DateTime.Now;
           string url = string.Empty;
           foreach (string s in fullFileList)
           {
               url = config.GetFileURL(folderName, s);
               d = GetFileDateTime(url);
               if (d.Date == TargetDay.Date)
                   result.Add(s);
           }
           return result;
       }

       private DateTime  GetFileDateTime(string fileURL)
       {
           DateTime r = DateTime.MinValue ;
           FtpWebRequest request = (FtpWebRequest)WebRequest.Create(fileURL); ;

           request.Method = WebRequestMethods.Ftp.GetDateTimestamp;
           request.Proxy = null;
           
           using (FtpWebResponse resp = (FtpWebResponse)request.GetResponse())
           {
               r=resp.LastModified;
           }
           return r;
       }
       
       private List<string> Response2List(FtpWebResponse response)
       {
           List<string> result = new List<string>();
           using (StreamReader reader = new StreamReader(response.GetResponseStream()))
           {
               string line = reader.ReadLine();
               while (line != null)
               {
                   result.Add(line);
                   line = reader.ReadLine();
               }
               reader.Close();
           }
           return result;
       }

       private bool isFtpFolderURL(string folderUrl)
       {
           string pattern = @"^(http|https|ftp)\://\w";
           Regex reg = new Regex(pattern, RegexOptions.Compiled | RegexOptions.IgnoreCase);
           return reg.IsMatch(folderUrl);
       }

       private bool isFolder(string folder)
       {
           string pattern = @"^[a-zA-Z_]";
           Regex reg = new Regex(pattern, RegexOptions.Compiled | RegexOptions.IgnoreCase);
           return reg.IsMatch(folder);
       }

       private List<string> GetFileList(string folderUrl)
       {
           try
           {
               if (!isFtpFolderURL(folderUrl))
                     return new List<string> ();

               FtpWebRequest request = (FtpWebRequest)WebRequest.Create(folderUrl);
               request.Method = WebRequestMethods.Ftp.ListDirectory;
               FtpWebResponse response = (FtpWebResponse)request.GetResponse();
               List<string> l = Response2List(response);
               response.Close();
               return l;
           }
           catch(Exception e)
           {
               Console.WriteLine(e.Message); 
               return new List<string> (); 
           }
       }
     
    }
}
